//
//  HACBrush.m
//  HStockCharts
//
//  Created by Hotacool on 2018/9/13.
//

#import "HACBrush.h"
#import "HACPainter.h"

@interface HACPainterBox : NSObject
@property (nonatomic, strong) id<HACAsynchronousAble> painter;
@property (nonatomic, assign) BOOL isUsed;
- (instancetype)initWithPainter:(id)painter isUsed:(BOOL)isUsed ;
@end
@implementation HACPainterBox
- (instancetype)initWithPainter:(id)painter isUsed:(BOOL)isUsed {
    if (self = [self init]) {
        _isUsed = isUsed;
        _painter = painter;
    }
    return self;
}
@end

@implementation HACPainterPool {
    NSMutableArray *_painters;
    long _cursor;
}
+ (instancetype)pool {
    HACPainterPool *pool = [[HACPainterPool alloc] init];
    return pool;
}
- (instancetype)init {
    if (self = [super init]) {
        _painters = [NSMutableArray array];
        _cursor = 0;
    }
    return self;
}

- (id<HACAsynchronousAble>)pop {
    if (_cursor < _painters.count) {
        HACPainterBox *box = _painters[_cursor++];
        return box.isUsed?nil:box.painter;
    }
    return nil;
}

- (void)push:(id<HACAsynchronousAble>)painter isUsed:(BOOL)isUsed {
    HACPainterBox *box = [[HACPainterBox alloc] initWithPainter:painter isUsed:isUsed];
    [_painters addObject:box];
}

- (NSArray *)allPainters {
    NSMutableArray *ret = [NSMutableArray arrayWithCapacity:_painters.count];
    [_painters enumerateObjectsUsingBlock:^(HACPainterBox*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [ret addObject:obj.painter];
    }];
    return ret;
}

- (HACPainterPool*)freePool {
    [_painters enumerateObjectsUsingBlock:^(HACPainterBox*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.isUsed = NO;
    }];
    _cursor = 0;
    return self;
}
@end

@implementation HACBrush

- (instancetype)initWithDataProvider:(id<HACChartDataProvider>)provider {
    if (self = [self init]) {
        self.provider = provider;
    }
    return self;
}

- (instancetype)init {
    if (self = [super init]) {
    }
    return self;
}

- (void)drawInLayer:(CALayer*)layer inRect:(CGRect)rect {
    if (!layer) {
        return;
    }
}

- (void)clean {}

- (void)removeBrush {}

#define POINT(_INDEX_) (CGPointFromString(points[_INDEX_]))
- (NSArray<NSArray*>*)_generateSubPointsFromArray:(NSArray*)points {
    NSMutableArray *subPoints;
    if (points && points.count > 0) {
        subPoints = [NSMutableArray array];
        NSMutableArray *temp;
        CGPoint lastPoint = CGPointMake(kDrawingInvaildValue, kDrawingInvaildValue); // 用于第一个值的判断
        for (int i = 0; i < points.count; i++) {
            CGPoint p = POINT(i);
            if (p.y == kDrawingInvaildValue) {
                // 无效值直接忽略
                if (lastPoint.y != kDrawingInvaildValue) {
                    if (temp) {
                        [subPoints addObject:temp];
                    }
                    temp = nil;
                } else {
                    continue;
                }
            } else {
                if (lastPoint.y == kDrawingInvaildValue) {
                    temp = [NSMutableArray array];
                }
                [temp addObject:NSStringFromCGPoint(p)];
            }
            if (i == points.count-1) {
                if (temp) {
                    [subPoints addObject:temp];
                }
            }
            lastPoint = p;
        }
    }
    return subPoints;
}

- (UIBezierPath *)_generatePathFromPoints:(NSArray *)pointsArray
                                 isSmooth:(BOOL)isSmooth {
    return [self _generatePathFromPoints:pointsArray isSmooth:isSmooth fillColor:nil InRect:CGRectZero];
}

- (UIBezierPath*)_generatePathFromPoints:(NSArray*)pointsArray
                                isSmooth:(BOOL)isSmooth
                               fillColor:(UIColor*)fillColor
                                  InRect:(CGRect)rect{
    UIBezierPath *smoothedPath;
    if (pointsArray.count > 1) {
        NSInteger granularity = 0;
        granularity = 20;//平滑曲线算法: Centripetal Catmull–Rom spline
        smoothedPath = [UIBezierPath bezierPath];
        if (isSmooth) { // 平滑曲线方法
            if (smoothedPath) {
                NSMutableArray *points = [pointsArray mutableCopy];
                
                // Add control points to make the math make sense
                [points insertObject:[points objectAtIndex:0] atIndex:0];
                [points addObject:[points lastObject]];
                
                CGPoint lastPoint = CGPointMake(kDrawingInvaildValue, kDrawingInvaildValue); // 用于第一个值的判断
                for (NSUInteger index = 1; index < points.count - 2; index++) {
                    CGPoint p0 = POINT(index - 1);
                    CGPoint p1 = POINT(index);
                    CGPoint p2 = POINT(index + 1);
                    CGPoint p3 = POINT(index + 2);
                    if (p0.y == kDrawingInvaildValue || p1.y == kDrawingInvaildValue || p2.y == kDrawingInvaildValue || p3.y == kDrawingInvaildValue) {
                        // 无效值直接忽略
                        lastPoint = p1;
                        continue;
                    } else {
                        if (lastPoint.y == kDrawingInvaildValue) {
                            // 有填充，加上首尾两点封闭
                            if (fillColor) {//第一个点
                                CGPoint pOrigin = CGPointMake(p0.x, rect.size.height);//接地
                                [smoothedPath moveToPoint:pOrigin];
                                [smoothedPath addLineToPoint:p0];
                            } else {
                                [smoothedPath moveToPoint:p0];
                            }
                        }
                        // 继续绘制后面的点
                        // now add n points starting at p1 + dx/dy up until p2 using Catmull-Rom splines
                        for (int i = 1; i < granularity; i++) {
                            
                            float t = (float) i * (1.0f / (float) granularity);
                            float tt = t * t;
                            float ttt = tt * t;
                            
                            CGPoint pi; // intermediate point
                            pi.x = 0.5 * (2*p1.x+(p2.x-p0.x)*t + (2*p0.x-5*p1.x+4*p2.x-p3.x)*tt + (3*p1.x-p0.x-3*p2.x+p3.x)*ttt);
                            pi.y = 0.5 * (2*p1.y+(p2.y-p0.y)*t + (2*p0.y-5*p1.y+4*p2.y-p3.y)*tt + (3*p1.y-p0.y-3*p2.y+p3.y)*ttt);
                            [smoothedPath addLineToPoint:pi];
                        }
                        
                        // Now add p2
                        [smoothedPath addLineToPoint:p2];
                        lastPoint = p1;
                    }
                }
                // finish by adding the last point
                if (fillColor) {//最后一点
                    CGPoint pOrigin = CGPointMake(POINT(points.count - 1).x, rect.size.height);//接地
                    [smoothedPath addLineToPoint:pOrigin];
                    [smoothedPath addLineToPoint:CGPointMake(POINT(0).x, rect.size.height)];
                } else {
                    [smoothedPath addLineToPoint:POINT(points.count - 1)];
                }
            }
        }
        else {
            NSMutableArray *points = [pointsArray mutableCopy];
            for (NSUInteger index = 0; index < points.count; index++) {
                if (index == 0) {
                    CGPoint p0 = POINT(index);
                    // 有填充，加上首尾两点封闭
                    if (fillColor) {//第一个点
                        CGPoint pOrigin = CGPointMake(p0.x, rect.size.height);//接地
                        [smoothedPath moveToPoint:pOrigin];
                        [smoothedPath addLineToPoint:p0];
                    } else {
                        [smoothedPath moveToPoint:p0];
                    }
                } else {
                    [smoothedPath addLineToPoint:POINT(index)];
                }
            }
            // finish by adding the last point
            if (fillColor) {//最后一点
                CGPoint pOrigin = CGPointMake(POINT(points.count - 1).x, rect.size.height);//接地
                [smoothedPath addLineToPoint:pOrigin];
                [smoothedPath addLineToPoint:CGPointMake(POINT(0).x, rect.size.height)];
            }
        }
    }
    return smoothedPath;
}

- (UIBezierPath*)_generateCandlePathInRect:(CGRect)rect
                                 highPoint:(CGPoint)hp
                                  lowPoint:(CGPoint)lp
                                    isFill:(BOOL)isFill {
    UIBezierPath *path;
    path = [UIBezierPath bezierPathWithRect:rect];
    //绘制上下影线
    [path moveToPoint:hp];
    if (!isFill) {
        [path addLineToPoint:CGPointMake(hp.x, rect.origin.y)];
        [path moveToPoint:CGPointMake(lp.x, CGRectGetMaxY(rect))];
    }
    [path addLineToPoint:lp];
    return path;
}
@end
